home *** CD-ROM | disk | FTP | other *** search
- /*
-
- License: This source code may not be used in other applications whether they
- be personal, commercial, free, or paid without written permission from Read It Later.
-
-
- /////////
- DEVELOPER API: readitlaterlist.com/api/
- /////////
-
- If you would like to customize Read It Later or build an application that works with
- Read it Later take a look at the READ IT LATER OPEN API:
- http://readitlaterlist.com/api/
-
- Suggestions for additions to Read It Later are VERY welcome. A large number of user
- suggestions have been implemented. Please let me know of any additional features you
- are seeking at: http://readitlaterlist.com/support/
-
- Thanks
-
- */
-
- Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-
- function RILassetManager() {
- // Set and create download directories
- this.DEFAULT_FOLDER_NAME = 'ReadItLater';
- this.PAGES_FOLDER_NAME = 'RIL_pages'; // !!!!! changes here should be checked against RIL.getItemForCurrentPage
- this.ASSETS_FOLDER_NAME = 'RIL_assets'; // !!!!! changes here should be checked against RIL.getItemForCurrentPage
-
- }
-
- RILassetManager.prototype = {
-
- // properties required for XPCOM registration:
- classDescription: "Read It Later Asset Manager Javascript XPCOM Component",
- classID: Components.ID("{b9b44920-aabb-11de-8a39-0800200c9a66}"),
- contractID: "@ril.ideashower.com/rilassetmanager;1",
-
- QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIRILassetManager]),
-
- //////////////////////////////////////////////////
-
- init : function()
- {
- // IO service not allowed because it is not threadsafe!
- this.FILE = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
- this.PREFS = Components.classes['@ril.ideashower.com/rilprefs;1'].getService().wrappedJSObject;
- this.JSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON);
-
- this.PATH_PROF = this.FILE.get("ProfD", Components.interfaces.nsIFile).path;
- this.FD = this.PATH_PROF.match(/([\/\\])/)[0];
-
- this.PATH_RIL = this.PREFS.get('offlinePath');
- this.PATH_RIL = this.PATH_RIL ? this.PATH_RIL : (this.PATH_PROF + this.FD + this.DEFAULT_FOLDER_NAME);
-
- this.PATH_PAGES = this.PATH_RIL + this.FD + this.PAGES_FOLDER_NAME;
- this.PATH_ASSETS = this.PATH_RIL + this.FD + this.ASSETS_FOLDER_NAME;
-
- this.DIR_RIL = this.dir(this.PATH_RIL, true);
- this.DIR_PAGES = this.dir(this.PATH_PAGES, true);
- this.DIR_ASSETS = this.dir(this.PATH_ASSETS, true);
- },
-
- file : function(path) {
- let file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(path);
- return file;
- },
-
- dir : function(path, createIfDoesntExist)
- {
- let file = this.file(path);
-
- if (createIfDoesntExist)
- {
- if (!file.exists() || !file.isDirectory()) file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
- }
-
- return file;
- },
-
- typeCastTrueFalseNull : function(string)
- {
- return string == 'true' ? true : string == 'false' ? false : string == 'null' || string == 'undefined' ? null : string;
- },
-
- pathsForLiteral : function( literal, baseURL, relative, forceType )
- {
- // because args come through as strings, need to do some type casting
- baseURL = this.typeCastTrueFalseNull(baseURL);
- relative = this.typeCastTrueFalseNull(relative);
- forceType = this.typeCastTrueFalseNull(forceType);
-
- try {
- // Find absolute path
- let absoluteURI = this.parseUri( literal, baseURL );
- let absolute = absoluteURI.spec;
-
- if (absoluteURI.scheme != 'http' && absoluteURI.scheme != 'https') return; // no other schemes allowed
-
- // Decode the url (just & right now)
- absolute = absolute.replace('&', '&');
-
-
- // Fix up the absolute path to use when saving to path
- // query string data should be moved to file name
- // Stylesheets should be forced to end in css
- // ex: img.jpg?test=1 => imgtest%31.jpg
- // ex: index.php?blah=1 => indexblah%31.css
-
- // Fix lastPathComponent as described above
- let pathParts = absoluteURI.path.split('/');
- let last = pathParts[ pathParts.length-1 ];
-
- // Move query string info into filename
- if (last)
- {
- let extension = absoluteURI.file.replace(/[^\.]*\.(.*)$/, '.$1');
- let newPath = last.replace(extension, '');
- newPath += absoluteURI.query ? encodeURIComponent(absoluteURI.query) : '';
- newPath += forceType ? (forceType==2 ? '.css' : '') : extension;
-
- pathParts[ pathParts.length-1 ] = newPath;
- }
-
- let absolutePath = this.cleanPathName( pathParts.join(this.FD) );
-
- // Break up path parts to figure out folders
- pathParts = absolutePath.split(this.FD);
-
- // Build Path
- let assetDomain = absoluteURI.host;
- let path = this.PATH_ASSETS + this.FD + assetDomain;
- for(let i in pathParts) {
- if (!pathParts[i]) continue;
- if (pathParts[i].length > 50)
- pathParts[i] = pathParts[i].substr(0, 50); // make sure no folder will be over file name limits
- path += this.FD + pathParts[i];
-
- }
-
-
- // -- Moved file exists check out and only used when it needs it -- //
-
-
- // Make relative Path
- // Remove front end of path (offline directory path)
- // second replace strips prefix slash if it exists so we don't get ../..//something
- // relative path should only have forward slashes: file://something/something
- let relativePath = path.replace( this.PATH_RIL , '' ).replace(new RegExp('^\\'+this.FD), '').replace(/\\/gi, '/');
-
- // If the path needs to be relative (for example its linked from inside a stylesheet, add the required number of ../
- if (relative) {
- let baseItemInfoJSON = this.pathsForLiteral( baseURL, baseURL, false, false );
- if (baseItemInfoJSON)
- {
- let baseItemInfo = this.JSON.decode(baseItemInfoJSON);
- let baseItemPathParts = baseItemInfo.assetRelativePath.split('/');
-
- let relativePrefix = '';
- let parts = baseItemPathParts.length - 3; //2 for the ../ added below, and 1 for moving out of current
- for(let i=0; i<parts; i++)
- {
- relativePrefix += '../';
- }
- relativePath = relativePrefix + relativePath;
- }
- // TODO - what to do for else?
-
- } else {
-
- // Needs to go out of RIL_pages and into RIL_assets, first ../ gets it out of items folder, second ../ gets it out of RIL_pages
- relativePath = '../../' + relativePath;
-
- }
-
- return this.JSON.encode({
- literal: literal,
- absolute: absolute,
- assetPath: path,
- assetRelativePath: relativePath,
- assetDomain: assetDomain,
- assetExists: this.assetExists(path)
- });
-
- } catch(e) {
- Components.utils.reportError('Error caused by '+ literal + "\n" + baseURL);
- Components.utils.reportError(e);
- }
- },
- cleanPathName : function(path)
- {
- path = path.replace( this.FD=='/' ? /\\/gi : /\//gi, '' ); // opp slash as defined in FD
- return path.replace(/[\=\?\&\%\;\:\*\"\<\>\|]/gi, '');
- },
-
- assetExists : function(assetPath)
- {
- let file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(assetPath);
- return file.exists();
- },
-
- // -- //
-
- folderPathForItemId : function(itemId, urlFormat) {
- let path = this.PATH_PAGES + this.FD + itemId + this.FD;
- if (urlFormat)
- return 'file:///' + path.replace(/\\/g,'/');
- else
- return path;
- },
-
- folderForItemId : function(itemId) {
- return this.file(this.folderPathForItemId(itemId));
- },
-
- removeFolderForItemId : function(itemId) { // TODO is the folder.exists check ness? Is that a point of slowdown?
- let folder = this.folderForItemId( itemId );
- if (folder.exists()) folder.remove(true);
- },
-
- // -- //
-
- removeAssetDomain : function(assetDomain) { // TODO is the folder.exists check ness? Is that a point of slowdown?
- let folder = this.file(this.PATH_ASSETS + this.FD + assetDomain);
- if (folder.exists()) folder.remove(true);
- },
-
- parseUri : function(urlStr, baseURL)
- {
- if (urlStr.length > 1250) return; //too long of a url locks browser in parseUri script
- var uri = {};
-
- if (baseURL && !urlStr.match(/^https?:/))
- {
- // if url starts with ./example remove ./
- urlStr = urlStr.replace(/^\.\//, '');
-
- // convert urlStr into a full absolute url
- let parsedBase = this.parseUri(baseURL);
- let baseRoot = parsedBase.protocol + '://' + parsedBase.authority + '/';
-
- if ( urlStr.match(/^\.\.?\//) ) // ../../format.html
- {
- let relativeBaseParts = parsedBase.relative.split('/');
- if (relativeBaseParts.length < 3)
- {
- urlStr = baseRoot + urlStr.replace(/^(\.\.\/){0,}/,'')
- }
- else
- {
- relativeBaseParts.shift(); //remove first which will be empty (x)/something/something/
- if (parsedBase.file || relativeBaseParts[relativeBaseParts.length-1].length==0) relativeBaseParts.pop(); //remove end (file)
-
- let end = relativeBaseParts.length - urlStr.match(/\.\.\//g).length;
- let rel = relativeBaseParts.slice(0,end>0?end:0).join('/');
- urlStr = baseRoot + (rel ? rel+'/' : '') + urlStr.replace(/^(\.\.\/){0,}/,'');
- }
-
- }
-
- else if (urlStr.match(/^\//)) // /format.html
- {
- urlStr = baseRoot.replace(/\/$/,'') + urlStr;
- }
-
- else
- { // format/format.html
- urlStr = baseRoot.replace(/\/$/,'') + parsedBase.directory.replace(/[^\/]*$/,'') + urlStr;
- }
-
- }
- else {
- uri.wasAbsolute = true;
- }
-
-
- var o = {
- strictMode: false,
- key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
- q: {
- name: "queryKey",
- parser: /(?:^|&)([^&=]*)=?([^&]*)/g
- },
- parser: {
- strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
- loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
- }
- }
-
- var m = o.parser[o.strictMode ? "strict" : "loose"].exec(urlStr),
- i = 14;
-
- while (i--) uri[o.key[i]] = m[i] || "";
-
- uri[o.q.name] = {};
- uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
- if ($1) uri[o.q.name][$1] = $2;
- });
-
- uri.spec = urlStr;
- uri.scheme = uri.protocol;
-
- return uri;
- },
-
- // returns an absolute from a relative or false if it already is an absolute
- getAbsoluteFromRelative : function(urlStr, baseURL)
- {
- let parsed = this.parseUri(urlStr, baseURL);
- return !parsed || !parsed.host || parsed.wasAbsolute ? false : parsed.spec;
- }
-
-
- };
-
- var components = [RILassetManager];
- function NSGetModule(compMgr, fileSpec) {
- return XPCOMUtils.generateModule(components);
- }
-